/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package knn;

import java.text.DecimalFormat;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.SortedSet;

/**
 *
 * @author jairo
 */
public class KNN {
	
	private int k;
	private AbstractCollection<Ejemplo> ejemplos;
	
	KNN(int k, AbstractCollection<Ejemplo> ejemplos){
		this.k = k;
		this.ejemplos = ejemplos;
	}
	
	public char clasificar(Ejemplo ejemplo) throws Exception{
		SortedSet<ParDistanciaResultado> masCercanos;
		masCercanos = ejemplo.obtenerMasCercanos(ejemplos);
		double valorE = 0;
		double valorP = 0;
		Iterator it = masCercanos.iterator();
		for (int i = 0; i < k; i++) {
			ParDistanciaResultado actual = (ParDistanciaResultado)it.next();	
			if (actual.getResultado() == 'e') {
				valorE = valorE + 1/(actual.getDistancia()*actual.getDistancia());
			} else {
				valorP = valorP + 1/(actual.getDistancia()*actual.getDistancia());
			}
		}
		if (valorE > valorP) {
			return 'e';
		} else {
			return 'p';
		}
	}
	
	public int[][] comprobar(AbstractCollection<Ejemplo> ejemplos) throws Exception{
		int count[][] = new int[2][2];
		count[0][0] = 0; // mal poison
		count[0][1] = 0; // bien poison
		count[1][0] = 0; // mal comestible
		count[1][1] = 0; // bien comestible
		
		Iterator it = ejemplos.iterator();
		while (it.hasNext()) {
			Ejemplo ejemplo = (Ejemplo)it.next();
			if (ejemplo.getVal(0) == 'e') {
				if (this.clasificar(ejemplo) == 'e') {
					count[1][1]++;
				} else {
					count[1][0]++;
				}
			} else {
				if (this.clasificar(ejemplo) == 'p') {
					count[0][1]++;
				} else {
					count[0][0]++;
				}
			}
		}
		return count;
	}
	
	static void probar(AbstractCollection<Ejemplo> ejemplos,
			int k, int verifI,int verifF) throws Exception {
		int numInst = ejemplos.size();
		AbstractCollection<Ejemplo> ejemplosCostruir = new ArrayList();
		AbstractCollection<Ejemplo> ejemplosVerif = new ArrayList();
		for (int i = 0; i < verifI; i++) {
			ejemplosCostruir.add((Ejemplo) ((ArrayList) ejemplos).get(i));
		}
		for (int i = verifI; i < verifF; i++) {
			ejemplosVerif.add((Ejemplo) ((ArrayList) ejemplos).get(i));
		}
		for (int i = verifF; i < numInst; i++) {
			ejemplosCostruir.add((Ejemplo) ((ArrayList) ejemplos).get(i));
		}
		
		//desordeno los ejemplos
		Collections.shuffle((ArrayList)ejemplosCostruir);
		Collections.shuffle((ArrayList)ejemplosVerif);
		
		long time1 = System.nanoTime();
		
		KNN ar = new KNN(k, ejemplosCostruir);
		
		int matriz[][] = ar.comprobar(ejemplosVerif);
		
		long time2 = System.nanoTime();
		double timeSpent = ((double)(time2-time1))*(Math.pow(10.0, -9.0));
		
		int pruebas = verifF - verifI;

		Double error = (1.0/(double)pruebas)*((double)matriz[1][0] + (double)matriz[0][0]);
		DecimalFormat twoDForm = new DecimalFormat("#.##");
		
		System.out.println("Para test = " + verifI + " a " + verifF + ", la matriz de confusion es:");
		System.out.println("     | Comestible | Venenoso");
		System.out.println("Bien | "+matriz[1][1] + "	| "+matriz[0][1]);
		System.out.println("Mal  | "+matriz[1][0] + "	| "+matriz[0][0]);
		System.out.println("Error: "+ twoDForm.format(error));
		System.out.println("Tiempo de ejecucion: "+ timeSpent);
		System.out.println("");
	}	
}
